﻿using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using CtefCrmImport.Common.Interfaces;
using CtefCrmImport.Common.Extensions;
using CtefCrmImport.Common.Models;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Crm.Sdk.Samples;

namespace CtefCrmImport.Common.Operations
{
    public class ImportDonors
    {
        private readonly ILogger logger;
        private CommonOperations common;
        private IDictionary<string, EntityReferenceCollection> fullNameContactMap;
        private IDictionary<string, EntityReferenceCollection> emailContactMap;
        private ServerConnection.Configuration config;

        public ImportDonors(ILogger logger, ServerConnection.Configuration config)
        {
            this.logger = logger;
            common = new CommonOperations(logger);
            this.config = config;
        }

        public void Run(string filePath)
        {
            Log("ImportDonors: start processing...");

            var donors = ParseFile(filePath);

            using (var serviceProxy = new OrganizationServiceProxy(config.OrganizationUri,
                                                                   config.HomeRealmUri,
                                                                   config.Credentials,
                                                                   config.DeviceCredentials))
            {
                // This statement is required to enable early-bound type support.
                serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

                IOrganizationService service = serviceProxy;

                common.CheckVersion(service);
                common.BuildContactMaps(service, out emailContactMap, out fullNameContactMap);
                common.ImportDonors(service, donors, emailContactMap, fullNameContactMap);
            }

            logger.Flush();
        }

        private IEnumerable<Donor> ParseFile(string filePath)
        {
            var result = new List<Donor>();

            if (!File.Exists(filePath))
            {
                Log("File not found: {0}", filePath);
                return result;
            }

            using (var reader = new StreamReader(filePath))
            {
                // skip header row
                reader.ReadLine();

                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (string.IsNullOrWhiteSpace(line)) continue;

                    result.Add(BuildDonor(line));
                }
            }

            Log("Number of records loaded: {0}", result.Count);
            return result;
        }

        private static Donor BuildDonor(string input)
        {
            var fields = input.Split('\t');

            var address = new Address
                              {
                                  AddressLine1 = fields[11],
                                  AddressLine2 = fields[12],
                                  City = fields[13],
                                  State = fields[14],
                                  Zip = fields[15]
                              };

            return new Donor
                            {
                                LastName = fields[0],
                                FirstName = fields[1],
                                MiddleName = fields[2],
                                ChineseName = fields[3],
                                PrimaryEmail = fields[16],
                                EmailForStudents = fields[17],
                                Address = address
                            };
        }

        private void Log(string format, params object[] args)
        {
            logger.Log(format, args);
        }
    }
}
